package main
import(
	"fmt"
	"os"
//	"runtime"
	"time"
)
func hello(){
	//time.Sleep(1*time.Second)
//	fmt.Println("======test=======")
for i:=1;i<5;i++{
	time.Sleep(100*time.Millisecond)
	fmt.Println(i)
}
}
func alphabets(){
	for i :='a';i<='e';i++{
		time.Sleep(400*time.Millisecond)
		fmt.Println(i)
	}
}
func world(done chan bool){
	fmt.Println("demo go route is going to sleep")
	time.Sleep(4*time.Second)
	fmt.Println("dmeo go routine awake and going to write to done")
	done <- true
}
func calcSq(number int,squareop chan int){
	sum :=0
	for number !=0{
		digit :=number % 10
		sum +=digit *digit
		number /=10
	}
	squareop <-sum
}
func calcC (number int,cubeop chan int){
	sum :=0
	for number !=0{
		digit :=number %10
		sum +=digit *digit *digit
		number /=10
	}
	cubeop <-sum
}
func sendData(sendch chan<- int){
	sendch <-10
}
func producer(chn1 chan int){
	for i:=0;i<10;i++{
		chn1 <-i
	}
	close(chn1)
}
type Task interface{
	DoTask() error
}
type Job struct{
	Task Task
}
var JobQueue chan Job
type Worker struct{
	WorkerPool chan chan Job
	JobChannel chan Job
	quit chan bool
}
func NewWorker(workerPool chan chan Job)Worker{
	return Worker{
		WorkerPool: workerPool,
		JobChannel: make(chan Job),
		quit: make(chan bool),
	}
}
func(w *Worker)Start(){
	go func(){
		for{
			w.WorkerPool <-w.JobChannel
			select{
			case job:=<-w.JobChannel:
				err:=job.Task.DoTask()
				if err !=nil{
					fmt.Println("task failure")
				}

			case <-w.quit:
				return
			}
		}
	}()
}
func (w *Worker)Stop(){
	go func(){
		w.quit <-true
	}()
}
type Sender struct{
	maxWorkers int
	WorkerPool chan chan Job
	quit chan bool

}
func NewSender(maxWorkers int)*Sender{
	Pool :=make(chan chan Job,maxWorkers)
	return &Sender{
		WorkerPool:Pool,
		maxWorkers:maxWorkers,
		quit:make(chan bool),
	}
}
func (s *Sender)Run(){
	for i:=0;i<s.maxWorkers;i++{
		worker :=NewWorker(s.WorkerPool)
		worker.Start()
	}
	go s.Send()
}
func (s *Sender)Quit(){
	go func(){
		s.quit <-true
	}()
}
func(s *Sender)Send(){
	for{
		select{
		case job:=<-JobQueue:
			go func(job Job){
				jobChan :=<-s.WorkerPool
				jobChan <-job
			}(job)
			case <-s.quit:
				return
			}
		}
	}
func InitPool(){
	maxWorkers :=4
	maxQueue :=20
	send :=NewSender(maxWorkers)
	JobQueue=make(chan Job,maxQueue)
	send.Run()
}
type Test struct{
	num int
}
func(t *Test)DoTask()error{
	f,err :=os.OpenFile("log.txt",os.O_RDWR|os.O_CREATE|os.O_APPEND,0777)
	if err !=nil{
		return err
	}
	defer f.Close()
	f.WriteString(fmt.Sprintf("this is :%d,time:%s \n",t.num,fmt.Sprintf("%s",time.Now())))
	return nil
}

func main(){
InitPool()
for i:=1;i<40;i++{
	task :=&Test{i}
	JobQueue <-Job{
		Task:task,
		}
	}
	time.Sleep(180*time.Second)
	close(JobQueue)
}
	/*
	ch :=make(chan int)
	go producer(ch)
	for v:=range ch{
		fmt.Println("received",v)
	}
}
	/*
	ch :=make(chan int)
	go producer(ch)
	for{
		v,ok :=<-ch
		if ok ==false{
fmt.Println("false")

			break
			}
			fmt.Println("received",v,ok)
		}
	}
	/*
cha1 :=make(chan int)
go sendData(cha1)
fmt.Println(<-cha1)
}
	/*
	ch :=make(chan int)
	ch <-5
}
	/*
	number :=589
	sqrch :=make(chan int)
	cubech :=make(chan int)
	go calcSq(number,sqrch)
	go calcC(number,cubech)
	squares,cubes :=<-sqrch,<-cubech
	fmt.Println("final output",squares+cubes)
}
	/*
	done :=make(chan bool)
	fmt.Println("Main going to call demo go goroutine")
	go world(done)
	<-done
	fmt.Println("Main received data")
}
/* for i:=0;i<10;i++{
		fmt.Println("======i========:",i)
		go hello()
		fmt.Println("current:",runtime.NumGoroutine())
	}
	fmt.Println("main function")
	*/
	/*
	go hello();
	go alphabets();
	time.Sleep(3000*time.Millisecond)
	fmt.Println("main terminated")

}
*/
